package com.kotlin.android.api

import com.kotlin.android.api.api.*
import com.kotlin.android.api.config.ApiConfig
import com.kotlin.android.ktx.NetState
import com.kotlin.android.ktx.ext.e
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope

/**
 *
 * Created on 2020-01-14.
 *
 * @author o.s
 */
open class BaseRepository {

    val api by lazy { RetrofitManager.api(Api::class.java) }
    val apiMisc by lazy { RetrofitManager.api(ApiMisc::class.java) }
    val apiCinema by lazy { RetrofitManager.api(ApiCinema::class.java) }
    val apiUser by lazy { RetrofitManager.api(ApiUser::class.java) }
    val apiTicket by lazy { RetrofitManager.api(ApiTicket::class.java) }
    val apiPayment by lazy { RetrofitManager.api(ApiPayment::class.java) }
    val apiCard by lazy { RetrofitManager.api(ApiCard::class.java) }
    val apiSnack by lazy { RetrofitManager.api(ApiSnack::class.java) }
    val apiCoupon by lazy { RetrofitManager.api(ApiCoupon::class.java) }
    val apiActivity by lazy { RetrofitManager.api(ApiActivity::class.java) }
    val apiMkt by lazy { RetrofitManager.api(ApiMkt::class.java) }
    val apiCount by lazy { RetrofitManager.api(ApiCount::class.java) }

    suspend fun <T : Any> safeApiCall(
        errorMessage: String? = null,
        call: suspend () -> ApiResult<T>
    ): ApiResult<T> {
        if (!NetState.isOk()) {
            return ApiResult.Error(ApiResult.ErrorCode.NET_ERROR, ApiConfig.NET_ERROR)
        }
        return try {
            call()
        } catch (e: Throwable) {
            e.printStackTrace()
            e.e()
            if (NetState.isOk()) {
                ApiResult.Error(ApiResult.ErrorCode.ERROR, errorMessage, e)
            } else {
                ApiResult.Error(ApiResult.ErrorCode.NET_ERROR, ApiConfig.NET_ERROR, e)
            }
        }
    }

    suspend fun <T : Any> converter(
        response: ApiResponse<T>,
        successBlock: (suspend CoroutineScope.(data: T) -> Unit)? = null,
        errorBlock: (suspend CoroutineScope.() -> Unit)? = null
    ): ApiResult<T> {
        return coroutineScope {
            val code = response.code
            val message = response.msg
            when (code) {
                ApiCode.RESULT_OK -> {
                    val t = response.data
                    if (t != null) {
                        successBlock?.let { it(t) }
                        ApiResult.Success(t)
                    } else {
                        errorBlock?.let { it() }
                        ApiResult.Error(ApiResult.ErrorCode.ERROR, message)
                    }
                }
                ApiCode.RESULT_LOGIN -> {
                    errorBlock?.let { it() }
                    ApiResult.Error(ApiResult.ErrorCode.NEED_LOGIN, message)
                }
                ApiCode.RESULT_LIMIT -> {
                    errorBlock?.let { it() }
                    ApiResult.Error(ApiResult.ErrorCode.RESULT_LIMIT, message)
                }
                else -> {
                    errorBlock?.let { it() }
                    ApiResult.Error(ApiResult.ErrorCode.ERROR, message)
                }
            }
        }
    }

}